﻿using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace ShinyWizard
{
    [TemplatePart(Name = TitleContentControlTemplatePartName, Type = typeof(ContentControl))]
    [TemplateVisualState(Name = SelectedVisualStateName, GroupName = SelectionsStatesGroupName)]
    [TemplateVisualState(Name = UnselectedVisualStateName, GroupName = SelectionsStatesGroupName)]
    public class WizardStep : ContentControl
    {
        #region Constants

        private const string TitleContentControlTemplatePartName = "TitleContentControl";
        private const string SelectionsStatesGroupName = "SelectionStates";
        private const string SelectedVisualStateName = "Selected";
        private const string UnselectedVisualStateName = "Unselected";

        #endregion

        #region Static

        public static readonly DependencyProperty TitleProperty = DependencyProperty.Register(
            "Title", 
            typeof(object), 
            typeof(WizardStep), 
            new PropertyMetadata(OnTitlePropertyChanged));
        public static readonly DependencyProperty TitleTemplateProperty = DependencyProperty.Register(
            "TitleTemplate", 
            typeof(DataTemplate), 
            typeof(WizardStep), 
            new PropertyMetadata(OnTitleTemplatePropertyChanged));
        public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register(
            "Description", 
            typeof(object), 
            typeof(WizardStep), 
            null);

        private static void OnTitlePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var step = (WizardStep)d;

            step.OnTitleChanged(e.OldValue, e.NewValue);
        }

        private static void OnTitleTemplatePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var step = (WizardStep)d;

            step.OnTitleTemplateChanged((DataTemplate)e.OldValue, (DataTemplate)e.NewValue);
        }
        #endregion

        #region Constructors

        public WizardStep()
        {
            DefaultStyleKey = typeof(WizardStep);
        }

        #endregion

        #region Properties

        private ContentControl TitleContentControl { get; set; }

        public object Title
        {
            get { return GetValue(TitleProperty); }
            set { SetValue(TitleProperty, value); }
        }

        public DataTemplate TitleTemplate
        {
            get { return (DataTemplate)GetValue(TitleTemplateProperty); }
            set { SetValue(TitleTemplateProperty, value); }
        }

        public object Description
        {
            get { return GetValue(DescriptionProperty); }
            set { SetValue(DescriptionProperty, value); }
        }

        private WizardControl ParentWizardControl
        {
            get
            {
                var wizardControl = Parent as WizardControl;
                if (wizardControl != null)
                {
                    return wizardControl;
                }

                for (var element = this as FrameworkElement; element != null; element = VisualTreeHelper.GetParent(element) as FrameworkElement)
                {
                    var control = element as WizardControl;
                    if (control != null)
                        return control;
                }
                return null;
            }
        }

        #endregion

        #region Methods

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            TitleContentControl = (ContentControl)GetTemplateChild(TitleContentControlTemplatePartName);

            UpdateTitleVisuals();
            ChangeVisualState(false);
        }

        protected virtual void OnTitleChanged(object oldHeader, object newHeader)
        {
            UpdateTitleVisuals();
        }

        protected virtual void OnTitleTemplateChanged(DataTemplate oldHeaderTemplate, DataTemplate newHeaderTemplate)
        {
            UpdateTitleVisuals();
        }

        private void UpdateTitleVisuals()
        {
            if (TitleContentControl == null)
                return;

            TitleContentControl.Content = Title;
            TitleContentControl.ContentTemplate = TitleTemplate;
        }

        private void ChangeVisualState(bool useTransitions)
        {
            if (ParentWizardControl != null
                && ReferenceEquals(ParentWizardControl.ActiveStep, this))
            {
                VisualStateManager.GoToState(this, SelectedVisualStateName, useTransitions);
            }
            else
            {
                VisualStateManager.GoToState(this, UnselectedVisualStateName, useTransitions);
            }
        }

        internal void UpdateVisualState()
        {
            ChangeVisualState(true);
        }

        #endregion
    }
}
